home *** CD-ROM | disk | FTP | other *** search
- /* DialogBits
- * providing a bunch of dialog manager snippets */
- /*************************************************************
- This sample shows how to deal with many of the most commonly asked Dialog Manager
- questions. Dimming edit lines, using userItems, restricting edit lines to
- specific lengths, and some other stuff is included here.
- The programming style used here is designed to clearly show the specific
- actions I'm taking, _not_ to show good coding practice. Obviously, you will
- want to modify and optimize this code for your specific application.
- C.K. Haun
- Apple Developer Tech Support
- *************************************************************/
- /*
- #include <Dialogs.h>
- #include <Controls.h>
- #include <QuickDraw.h>
- #include <Windows.h>
- #include <ToolUtils.h>
- #include <OSUtils.h>
- #include <Menus.h>
- #include <Fonts.h>
- #include <resources.h>
- */
- /* item numbers */
- enum {
- kIconItem = 4, kBottomEditLine, kSpinItem, kTopEditLine, kEditCheckBox, kBorderBox, kDimmingBox = 10
- };
- /* this stuff would normally be in your .h file, but in this simple example */
- /* I just put them here */
- #define kSampleDialog 128
- #define kBaseSpinIcon 129
- #define kReturnKey 0x0D
- #define kEnterKey 0x03
- #define kEscKey 0x1B
- #define kTabKey 9
- #define ok 1
- #define cancel 2
- typedef unsigned char Str31[32];
- enum {
- kBackSpace = 8, kLeftArrow = 0x1C, kRightArrow, kUpArrow, kDownArrow, kDeleteKey = 0x7F
- };
- /* prototypes */
- ControlHandle SnatchHandle(DialogPtr thebox, short theGetItem);
- void SpinIt(DialogPtr theDialog);
- pascal Boolean filterIt(DialogPtr dialer, EventRecord *myDialogEvent, short *theDialogItem);
- Boolean IsEditKey(char theKey);
- void IBeamIt(WindowPtr dwind);
- pascal void BorderDefault(WindowPtr dwind, short dinum);
- pascal void DimEditLine(WindowPtr dwind, short dinum);
- #define nil 0
- main()
- {
- DialogPtr myDialog = nil;
- short hitItem = 0;
- Rect tempRect;
- short tempItem;
- Handle tempHandle;
- Boolean tBool;
- InitGraf((Ptr)&thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- InitCursor();
- myDialog = GetNewDialog(kSampleDialog, nil, (WindowPtr)-1);
- /* set up our user items for various things */
- GetDItem(myDialog, kBorderBox, &tempItem, &tempHandle, &tempRect);
- SetDItem(myDialog, kBorderBox, tempItem, (Handle)BorderDefault, &tempRect);
- GetDItem(myDialog, kDimmingBox, &tempItem, &tempHandle, &tempRect);
- SetDItem(myDialog, kDimmingBox, tempItem, (Handle)DimEditLine, &tempRect);
-
- tempHandle = (Handle)SnatchHandle(myDialog, kEditCheckBox);
- SetCtlValue((ControlHandle)tempHandle, false);
- /* and since I want this edit line dimmed when the box first shows up, I'll */
- /* select the other edit line */
- SelIText((DialogPtr)myDialog, kTopEditLine, 0, 0);
- ShowWindow((WindowPtr)myDialog);
- DrawDialog(myDialog);
- do {
- ModalDialog((ProcPtr)filterIt, &hitItem);
- switch (hitItem) {
- case kEditCheckBox:
- /* edit line dim checkbox */
- tempHandle = (Handle)SnatchHandle(myDialog, kEditCheckBox);
- tBool = GetCtlValue((ControlHandle)tempHandle);
- if(tBool)
- tBool = false;
- else
- tBool = true;
- /* tBool ? tBool = false : tBool = true; */
- SetCtlValue((ControlHandle)tempHandle, tBool);
- if (!tBool) { /* they turned the edit line off, we need to switch out of the EL if its */
- /* active */
- if (((DialogPeek)myDialog)->editField + 1 == kBottomEditLine)
- SelIText((DialogPtr)myDialog, kTopEditLine, 0, 0);
- }
- GetDItem(myDialog, kDimmingBox, &tempItem, &tempHandle, &tempRect);
- InvalRect(&tempRect);
- break;
- }
- } while (hitItem != 1 && hitItem != 2);
- DisposDialog(myDialog);
- }
-
- /* My dialog filter. It's pretty crowded here, since I'm showing lots of */
- /* stuff. You'd of course want it neatened up a bit */
- pascal Boolean filterIt(DialogPtr dialer, EventRecord *myDialogEvent, short *theDialogItem)
- {
- WindowPtr temp;
- char theKey;
- Rect tempRect;
- short tempItem;
- Handle tempHandle;
- long tilticks;
- Boolean returnVal = false;
- GetPort(&temp);
- SetPort(dialer);
-
- /**********************************************************************/
- /* Use something like this if you want to do any idle time drawing in your */
- /* dialog, like a clock, flashing cursor, or a classy animated icon like I'm using */
- /**********************************************************************/
- SpinIt(dialer);
-
- /**********************************************************************
- IBeamIt changes the cursor to an IBeam cursor when the cursor is over
- the active edit line
- **********************************************************************/
- IBeamIt(dialer);
-
- /*************************************************************/
- /* Some key filtering schemes follow. The first is the standard filter to */
- /* recognize 'return' as OK and 'ESC' as cancel. What this really means */
- /* is that I never ever want to have to use the mouse to click the cancel */
- /* buttton ever again, you can just cut and paste this code from now on. */
- /***********************************************************************/
- /* do standard filtering for escape and return as OK and Cancel aliases */
- /* We also invert the button in the dialog, so the user get's visual feedback */
- /* about the action they just took */
- if ((myDialogEvent->what == keyDown) || (myDialogEvent->what == autoKey)) {
- theKey = myDialogEvent->message & charCodeMask;
- switch (theKey) {
- case kReturnKey:
- case kEnterKey: /* enter key */
- /* This filters for Return or Enter as item 1, and Esc as item 2 */
- *theDialogItem = 1; /* change whatever the current item is to the OK item */
- /* now we need to invert the button */
- HiliteControl(SnatchHandle(dialer, ok), inButton);
- Delay(8, &tilticks); /* wait about 8 ticks so they can see it */
- HiliteControl(SnatchHandle(dialer, ok), false);
- SetPort(temp);
- returnVal = true;
- break;
- /* This filters the escape key as the same as item 2 (the canx button, usually ) */
- case kEscKey:
- *theDialogItem = 2;
- HiliteControl(SnatchHandle(dialer, cancel), inButton);
- Delay(8, &tilticks); /* wait about 8 ticks so they can see it */
- HiliteControl(SnatchHandle(dialer, cancel), false);
- SetPort(temp);
- returnVal = true;
- break;
- case kTabKey:
- /* I'm filtering the tab key here so the user cannot tab to */
- /* my inactive edit line */
- if (!GetCtlValue((ControlHandle)SnatchHandle(dialer, kEditCheckBox)))
- returnVal = true; /* don't allow edit line swaps */
- break;
- }
- }
-
- /********************************************************************************/
- /* Here's another kind of key filtering you need every so often, text or numeric */
- /* filtering. In this case, we're only going to allow non-numeric characters in */
- /* the edit line we have installed in this dialog */
- /* Any number will be eaten, and a beep generated */
- /**************************************************/
- if ((myDialogEvent->what == keyDown) || (myDialogEvent->what == autoKey)) {
- theKey = myDialogEvent->message & charCodeMask;
-
- if ((theKey > 0x30 && theKey < 0x39) && ((DialogPeek)dialer)->editField + 1 == kBottomEditLine) {
- /* Dang, it's a number and in the wrong edit line, reject it */
- SysBeep(1); /* complain a little */
- returnVal = true; /* tell the dialog manager
- /* that we handled this already and */
- /* it doesn't have to, so the keystroke will _not_ get */
- /* added to the edit line */
-
- }
- }
-
- /********************************************************************************/
- /* Here's yet another kind of key filtering you need every so often. */
- /* I'm going to restrict the amount of text in the edit line to just 25 characters */
- /**************************************************/
-
- if (((myDialogEvent->what == keyDown) || (myDialogEvent->what == autoKey)) &&
- ((DialogPeek)dialer)->editField + 1 == kTopEditLine) {
- Str31 myStr;
- GetDItem(dialer, kTopEditLine, &tempItem, &tempHandle, &tempRect);
- GetIText(tempHandle, myStr);
- if (myStr[0] > 25) { /* over 25, see what it is */
- theKey = myDialogEvent->message & charCodeMask;
- if (IsEditKey(theKey)) {
- returnVal = false; /* don't filter out editing keys */
- } else {
- SysBeep(1); /* complain a little */
- returnVal = true; /* tell the dialog manager that we handled this already and */
- /* it doesn't have to, so the keystroke will _not_ get */
- /* added to the edit line */
-
- }
- }
- }
- if (myDialogEvent->what == mouseDown) {
- Point willy;
- willy = (myDialogEvent->where);
- GlobalToLocal(&willy);
- GetDItem(dialer, kIconItem, &tempItem, &tempHandle, &tempRect);
- if (PtInRect(willy, &tempRect)) {
- Boolean hiLit = false;
- Point tempPoint;
- /* invert my icon, and track it whilst the user holds the mouse down */
- InvertRect(&tempRect);
- hiLit = true;
- while (StillDown()) {
- GetMouse(&tempPoint); /* returns point in local coords */
- if (PtInRect(tempPoint, &tempRect)) {
- /* in the rect. See if it's hilighted or not */
- if (!hiLit) {
- hiLit = true;
- InvertRect(&tempRect);
- }
- } else {
- /* not in the rectangle. If it's hilit, get rid of that */
- if (hiLit) {
- hiLit = false;
- InvertRect(&tempRect);
- }
- }
- }
- if (hiLit) {
- /* if it's still hilited when the mouse comes up, then that means the */
- /* user stayed in and wants to take this icon action */
- InvertRect(&tempRect); /* clear the hiliting if it's still lit */
- *theDialogItem = kIconItem;
- returnVal = true; /* telling the Dialog Manager we handled it, pass item back */
- }
- } else {
- /* first see if we even care about this click. If the check box is true, then */
- /* both edit lines are active, let the dialog manager handle it */
- if (GetCtlValue(SnatchHandle(dialer, kEditCheckBox))) {
- returnVal = false; /* DM will handle */
- } else {
- /* OK, so the edit line checkbox is NOT set, which means that we don't want */
- /* hits in the inactive edit line to do anything. So, see if the hit was */
- /* in the edit line, and report 'true' if it was, telling the Dialog Manager that */
- /* you handled the event and it should do nothing */
- GetDItem(dialer, kBottomEditLine, &tempItem, &tempHandle, &tempRect);
- if (PtInRect(willy, &tempRect)) {
- returnVal = true;
- } else {
- returnVal = false;
- }
- }
- }
- }
- return(returnVal);
- }
-
- void SpinIt(DialogPtr theDialog)
- {
- static short pos;
- static long count;
- Handle myIcon;
- Rect tempRect;
- short tempItem;
- Handle tempHandle;
-
- if (TickCount() > count + 10) {
- count = TickCount();
- myIcon = GetIcon(pos + kBaseSpinIcon);
- /* you could have a rect in this function, but that'd require you to change it all
- * the time when you move the item around in your dialog. So, we'll reference it
- * from the dialog record instead */
- GetDItem(theDialog, kSpinItem, &tempItem, &tempHandle, &tempRect);
- PlotIcon(&tempRect, myIcon);
- ReleaseResource(myIcon);
- pos++;
- if (pos > 3)
- pos = 0;
- }
- }
-
- /* BorderDefault draws a heavy border around the default button (in this case the OK button ) */
- pascal void BorderDefault(WindowPtr dwind, short dinum)
- {
- #pragma unused (dinum)
- short itemtype;
- Handle itemhandle;
- Rect borderRect;
- GetDItem(dwind, ok, &itemtype, &itemhandle, &borderRect);
- /* ok is defined as 1 in the interfaces. If you'd like another item outlined, */
- /* change this number, of course. */
- InsetRect(&borderRect, -4, -4);
- PenSize(3, 3);
- FrameRoundRect(&borderRect, 16, 16);
- PenSize(1, 1);
- }
-
- /* This userItem dims the bottom edit line if the check box is not checked */
- pascal void DimEditLine(WindowPtr dwind, short dinum)
- {
- ControlHandle tempCont;
- tempCont = SnatchHandle(dwind, kEditCheckBox);
- if (GetCtlValue(tempCont)) {
- /* the edit line should be active here, so don't overpaint */
- } else {
- PenState thePen;
- short itemType;
- Handle itemHandle;
- Rect dimRect;
- GetPenState(&thePen);
- GetDItem(dwind, dinum, &itemType, &itemHandle, &dimRect);
- PenMode(notPatBic);
- PenPat(&gray);
- PaintRect(&dimRect);
- SetPenState(&thePen);
-
- }
- }
-
- /* a little utility to see if the current key is an edit-type key */
- Boolean IsEditKey(char theKey)
- {
- register qq;
- char editChars[5] = {
- kLeftArrow, kUpArrow, kRightArrow, kDownArrow, kBackSpace
- };
- for (qq = 0; qq < 6; qq++) {
- if (theKey == editChars[qq])
- return(true);
- }
- return(false);
- }
-
- /* changes the cursor to an IBeam if it's over an active edit line, or to the */
- /* arrow if it's not */
- void IBeamIt(WindowPtr dwind)
- {
- Point mouseAt;
- short itemtype;
- Handle itemhandle;
- Rect borderRect;
- short itemNum;
- /* first get the current edit line out of the dialog record */
- itemNum = ((DialogPeek)dwind)->editField + 1; /* always stored 1 less */
- GetDItem(dwind, itemNum, &itemtype, &itemhandle, &borderRect);
- GetMouse(&mouseAt);
- if (PtInRect(mouseAt, &borderRect)) {
- SetCursor(*(GetCursor(1)));
- } else {
- InitCursor();
-
- }
- }
-
- /* Gets the ControlHandle for the item you want in the dialog box thebox. */
- /* Handy for setting checkboxes and radio buttons */
- ControlHandle SnatchHandle(DialogPtr thebox, short theGetItem)
- {
- short itemtype;
- Rect itemrect;
- Handle thandle;
-
- GetDItem(thebox, theGetItem, &itemtype, &thandle, &itemrect);
- return((ControlHandle)thandle);
- }
-